using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Text.RegularExpressions;
using System.IO;

public class lwAssetHolderEditor : EditorWindow {
	
	private AssetArray[] listAssets;
	private List<string> indexAssets;
	private List<System.Type> typeAssets;
	private List<List<BuildTarget>> targetAssets;
	
	private string sXmlConfiguration = string.Empty;
	
	// Liste de tout les objets affichés dans l'assetHolder
	private Object[][] listObjects;
	
	// Tableau de booléen pour les dossiers contenant les tableaux de l'assetHolder
	private bool[] folderArrays;
	
	//private bool bXmlNotFound = false;
	
	private string[] sMenus = {"Manage Assets", "Manage XML"};
	
	private int nMenuSelected = 0;
	
	private GUIStyle errorStyle;
	
	private GUIStyle titleStyle;
	
	private GUIStyle selectLabelStyle;
	
	private GUIStyle selectedLabelStyle;
	
	private int nCurrentSelected;
	
	private Vector2 scrollXML;
	private Vector2 scrollAsset;
	
	private const float HEIGHT_SCROLL_XML = 200;
	private const float HEIGHT_SCROLL_ASSET = 750;
	
	private string[] sTarget = {"WINDOWS", "MAC", "ANDROID", "IOS", "WEB"};
	private BuildTarget[] pBuildTarget = {BuildTarget.StandaloneWindows, BuildTarget.StandaloneOSXIntel, BuildTarget.Android, BuildTarget.iPhone, BuildTarget.WebPlayer};
	
	private string nameNewAsset  = string.Empty;
	private string typeNewAsset  = string.Empty;
	private int    newSize       = 1;
	private bool   bAllTarget     = false;
	private bool[] bSpecialTarget = {false, false, false, false, false};
	
	
	private string nameModifiedAsset = string.Empty;
	private string typeModifiedAsset = string.Empty;
	private int modifiedCount = 1;
	private List<BuildTarget> targetModifiedAsset = null;
	private bool   bModifiedAllTarget     = false;
	private bool[] bModifiedSpecialTarget = {false, false, false, false, false};
	
	private static lwAssetHolderEditor window = null;
	
//	private bool bChanged;
	
	// On initialise l'inspector quand on arrive dessus
	[MenuItem("Tools/LWS/Asset Holder", false, 0)]
	static public void Init()
	{
		window = EditorWindow.GetWindow( typeof(lwAssetHolderEditor) ) as lwAssetHolderEditor;
		
		string pathToXML = Application.dataPath + "/AssetHolders/" + lwBuildSettings.GetGameVersionName() + "/AssetHolder.xml";

		if( File.Exists( pathToXML ) )
			window.sXmlConfiguration = pathToXML;
		else if(EditorUtility.DisplayDialog("Create ?", pathToXML + " does not exist.\n Do you want to create it?" , "Yes", "No"))
		{
			Directory.CreateDirectory(Path.GetDirectoryName(pathToXML));
			StreamWriter sw = new StreamWriter(pathToXML);
			sw.WriteLine("<HOLDER>");
			sw.WriteLine("</HOLDER>");
			sw.Close();
			window.sXmlConfiguration = pathToXML;
			AssetDatabase.Refresh();
		}
		
		//draggableLabels = new List<DraggableLabel>();
		
		window.Initialize();
		
		window.errorStyle = new GUIStyle();
		window.errorStyle.normal.textColor = Color.red;
		window.errorStyle.fontStyle = FontStyle.Bold;
		window.errorStyle.alignment = TextAnchor.MiddleCenter;
		
		window.titleStyle = new GUIStyle();
		window.titleStyle.normal.textColor = Color.white;
		window.titleStyle.fontSize = 15;
		window.titleStyle.fontStyle = FontStyle.Bold;
		window.titleStyle.alignment = TextAnchor.MiddleCenter;
		
		window.selectLabelStyle = new GUIStyle();
		window.selectLabelStyle.normal.textColor = Color.white;
		window.selectLabelStyle.alignment = TextAnchor.MiddleCenter;
		
		window.selectedLabelStyle = new GUIStyle();
		window.selectedLabelStyle.normal.textColor = Color.cyan;
		window.selectedLabelStyle.alignment = TextAnchor.MiddleCenter;
		
		window.Selected = -1;
		window.scrollXML = Vector2.zero;
		window.scrollAsset = Vector2.zero;
		
		window.minSize = new Vector2(400, HEIGHT_SCROLL_ASSET + 50);
		window.title = " Asset Holder";
		//currentLabelDragged = null;
	}
	
	
	public void OnGUI()   
   	{
		//EditorGUIUtility.LookLikeInspector();
		
		/*string sXMLPath = EditorGUILayout.TextField("XML",sXmlConfiguration, GUI.skin.textField);
		Rect rectTextField = GUILayoutUtility.GetLastRect();
		
		EditorGUILayout.BeginHorizontal();
		if(GUILayout.Button("Open"))
			sXMLPath = EditorUtility.OpenFilePanel("Open XML", "", "xml");
		if(GUILayout.Button("Create"))
		{
			sXMLPath = EditorUtility.SaveFilePanel("Create XML", "", "", "xml");
			if(!string.IsNullOrEmpty(sXMLPath))
			{
				StreamWriter sw = new StreamWriter(sXMLPath);
				sw.WriteLine("<HOLDER>");
				sw.WriteLine("</HOLDER>");
				sw.Close();
			}
		}
		EditorGUILayout.EndHorizontal();*/
		/*
		EditorGUILayout.Space();
		
		EventType eventType = Event.current.type;
		if (eventType == EventType.DragUpdated || eventType == EventType.DragPerform)
		{
			// Ensure the drag/drop is within our timeline area:
			if (rectTextField.Contains(Event.current.mousePosition))
			{
				// Show a copy icon on the drag
				DragAndDrop.visualMode = DragAndDropVisualMode.Copy;

				if (eventType == EventType.DragPerform)
				{
					DragAndDrop.AcceptDrag();
					
					if(DragAndDrop.paths[0].EndsWith(".xml"))
					{
						sXMLPath = Path.GetFullPath(DragAndDrop.paths[0]);
						Repaint();
					}
					else
						Debug.LogWarning(Path.GetFileName(DragAndDrop.paths[0]) + " is not an XML file");
				}

				Event.current.Use();
			}
		}
		
		if(sXMLPath != sXmlConfiguration)
		{
			sXmlConfiguration = sXMLPath;
			Initialize();
		}*/
		
		if(string.IsNullOrEmpty(sXmlConfiguration))
		{
			EditorGUILayout.LabelField("XML not found !", errorStyle);
			return;
		}
		
		GUILayout.BeginHorizontal(GUI.skin.box);
		nMenuSelected = GUILayout.SelectionGrid(nMenuSelected, sMenus, 2);
		GUILayout.EndHorizontal();
		
		EditorGUILayout.Space();
		
		if(nMenuSelected == 0)
			DisplayManageAsset();
		else
		{
			DisplayManageXML();
			HandleKeyPressed();
		}
		
		//if(GUI.changed)
		//	EditorUtility.SetDirty(m_target);
	}
	
	void HandleKeyPressed()
	{
		if(Selected == -1 || Event.current.type != EventType.KeyDown)
			return;
		
		if(Event.current.keyCode == KeyCode.Delete
			&& EditorUtility.DisplayDialog("Delete ?", "Are you sure to delete " + indexAssets[Selected] + " ? ", "Yes", "No"))
				DeleteSelected();
		
		if(Event.current.keyCode == KeyCode.UpArrow)
			Selected = Mathf.Clamp(Selected - 1, 0 , indexAssets.Count - 1);
		if(Event.current.keyCode == KeyCode.DownArrow)
			Selected = Mathf.Clamp(Selected + 1, 0 , indexAssets.Count - 1);
		
		if(Event.current.keyCode == KeyCode.PageUp)
			Selected = 0;
		if(Event.current.keyCode == KeyCode.PageDown)
			Selected = indexAssets.Count - 1;
	}
	
	void WriteXml( XmlDocument xmlDoc, string sXml )
	{
		XmlWriterSettings settings = new XmlWriterSettings(); 
		settings.Encoding = new System.Text.UTF8Encoding(false); // The false means, do not emit the BOM. 
		settings.Indent = true;
		settings.IndentChars = ( "\t" );
		using (XmlWriter writer = XmlWriter.Create(sXml, settings)) 
		{ 
			xmlDoc.Save(writer); 
		}
	}
	
	void DeleteSelected()
	{
		
		for(int i = Selected; i < listAssets.Length - 1; i++)
			listAssets[i] = listAssets[i+1];
		System.Array.Resize<AssetArray>(ref listAssets, listAssets.Length - 1);
		
		for(int i = Selected; i < listObjects.Length - 1; i++)
			listObjects[i] = listObjects[i+1];
		listObjects = Resize<Object>(listObjects, listObjects.Length - 1);
		
		indexAssets.RemoveAt(Selected);
		typeAssets.RemoveAt(Selected);
		
		XmlDocument xmlDoc = new XmlDocument();

	    xmlDoc.Load(sXmlConfiguration);
	
	    XmlNodeList nodeAssetList = xmlDoc.GetElementsByTagName("ASSETARRAY");
		
		XmlNodeList nodeHolder = xmlDoc.GetElementsByTagName("HOLDER");
		
		nodeAssetList[Selected].RemoveAll();
		
		nodeHolder[0].RemoveChild(nodeAssetList[Selected]);
		
		WriteXml( xmlDoc, sXmlConfiguration );
		
		Selected = Mathf.Clamp(Selected, 0, listAssets.Length - 1);
	}
	/*
	void ReorderPanel()
	{
		for(int i = 0; i < draggableLabels.Count; i++)
			draggableLabels[i].Position = new Vector2(0, i*30 + 270);
	}
	*/
	void DisplayManageAsset()
	{
		// Tant que l'on n'est pas initialisé on affiche rien
			if(indexAssets == null || typeAssets == null)
				return;
			
			// Index qui permet de savoir quel booléen correspond à quel dossier
			int idxFolder = 0;
			
			scrollAsset = GUILayout.BeginScrollView(scrollAsset, GUI.skin.box, GUILayout.Height(HEIGHT_SCROLL_ASSET));
		
			// Pour chaque élément de l'assetHolder
			for(int i = 0; i < indexAssets.Count; i++)
			{
				string key = indexAssets[i];
				
				bool bInPlatform = true;
				if(targetAssets[i].Count > 0 && !targetAssets[i].Contains(EditorUserBuildSettings.activeBuildTarget))
					bInPlatform = false;
			
				bool bShow = true;
				// Si on est dans le cas d'un tableau
				if(listObjects[i].Length > 1)
				{
					bShow = folderArrays[idxFolder];
					if(!bInPlatform)
						GUI.color = Color.yellow;
					else
						GUI.color = Color.white;
				
					// On définit un folder
					folderArrays[idxFolder] = EditorGUILayout.Foldout(folderArrays[idxFolder], key);
				
					// On passe au prochain booléen
					idxFolder++;
				}
				
				if(bShow)
				{
					
					EditorGUI.indentLevel = listObjects[i].Length > 1 ? 2 : 1;
				
					// On affiche tout les éléments du tableau
					for(int j = 0; j < listObjects[i].Length; j++)
					{
						string label = key;
						// Si on est dans le cas d'un tableau on affiche l'indice en tant que label
						if(listObjects[i].Length > 1)
							label = j.ToString();
						// On affiche un objectField
						if(!bInPlatform)
						{
							GUI.color = Color.yellow;
						}
						
				
						Object newObject = EditorGUILayout.ObjectField(label, listObjects[i][j], typeAssets[i], false);
						GUI.color = Color.white;
						string path = AssetDatabase.GetAssetPath(newObject);
					
						if(newObject != listObjects[i][j])
						{
							if(!path.StartsWith("Assets/AssetHolders/Resources/"))
								Debug.LogWarning("Your Asset is not in the AssetHolders/Resources/ directory");
							// Si on mets none on efface la référence
							else if(string.IsNullOrEmpty(path))
							{
								listObjects[i][j] = null;
								listAssets[i][j] = string.Empty;
								SaveXML();
							}
							// Si l'objet renseigné n'est pas dans le dossier resources on le refuse
							else
							{
								// Sinon on met à jour l'objectField tout en renseignant le chemin de l'objet dans l'assetHolder
								listObjects[i][j] = newObject;
								path = GetResourcePath(path);
								listAssets[i][j] = path;
								SaveXML();
							}
						}
	
					}
				
					
				}
			}
		
			GUILayout.EndScrollView();
		
			/*GUI.enabled = bChanged;
			if(GUILayout.Button("Save changes"))
			{
				bChanged = false;
				SaveXML();
			}
			GUI.enabled = true;*/
	}
	
	void SaveXML()
	{
		XmlDocument xmlDoc = new XmlDocument();

	    xmlDoc.Load(sXmlConfiguration);
	
	    XmlNodeList nodeList = xmlDoc.GetElementsByTagName("ASSETARRAY");

		for(int i = 0; i < nodeList.Count; i++)
		{	
			XmlNodeList pathList = nodeList[i].ChildNodes;
			for(int j = 0; j < pathList.Count; j++)
			{
				 pathList[j].Attributes["path"].Value = listAssets[i][j];
			}
		}
		
		WriteXml( xmlDoc, sXmlConfiguration );
	}
	
	void DisplayManageXML()
	{
		
		Rect scrollList;
		float sizeY = 20;
		int countTarget = 0;
		
		scrollXML = GUILayout.BeginScrollView(scrollXML, GUI.skin.box, GUILayout.Height(HEIGHT_SCROLL_XML));
		for(int i = 0; i < indexAssets.Count; i++)
		{
			if(Selected == i)
				EditorGUILayout.LabelField(indexAssets[i], selectedLabelStyle, GUILayout.Height(sizeY));
			else
				EditorGUILayout.LabelField(indexAssets[i], selectLabelStyle, GUILayout.Height(sizeY));
		}
		GUILayout.EndScrollView();
		scrollList = GUILayoutUtility.GetLastRect();
		
		sizeY += 4;
		
		if(Event.current.type == EventType.MouseDown)
		{
			float mousePosY = Event.current.mousePosition.y;
			if(scrollList.y <= mousePosY  && mousePosY <= scrollList.y + scrollList.height)
			{
				int newSelected = Mathf.FloorToInt((mousePosY - scrollList.y + scrollXML.y)/sizeY);
				if(newSelected < indexAssets.Count)
				{
					if(newSelected == Selected)
						Selected = -1;
					else
						Selected = newSelected;
					Repaint();
				}
			}
		}
		
		
		
		DisplayModifyAsset();
		
		if(GUILayout.Button("Generate Enum"))
			GenerateEnum();
		
		EditorGUILayout.Space();
		
		EditorGUILayout.LabelField("Add Asset", titleStyle);
		nameNewAsset = EditorGUILayout.TextField("Name", nameNewAsset);
		typeNewAsset = EditorGUILayout.TextField("Type", typeNewAsset);
		newSize = EditorGUILayout.IntField("Array Size", newSize);
		
		newSize = Mathf.Clamp(newSize, 1, 50);
		
		bool allTarget = EditorGUILayout.Toggle("All Targets", bAllTarget);
		
		if(bAllTarget != allTarget)
		{
			bAllTarget = allTarget;
			for(int i = 0; i < bSpecialTarget.Length; i++)
				bSpecialTarget[i] = bAllTarget;
		}
		
		for(int i = 0; i < bSpecialTarget.Length; i++)
		{
        	bSpecialTarget[i] = EditorGUILayout.Toggle("\t" + sTarget[i], bSpecialTarget[i]);
			if( allTarget && allTarget != bSpecialTarget[i] )
			{
				bAllTarget = bSpecialTarget[i];
			}
			if( !bAllTarget && bAllTarget != bSpecialTarget[i] )
			{
				countTarget++;
			}
		}
		
		if( countTarget == sTarget.Length )
		{
			bAllTarget = true;
		}
		
		if(GUILayout.Button("Add"))
			AddAsset();
	}
	
	void AddAsset()
	{
		
		bool bAdd = true;
		
		bool bUniversal = true;
		bool bAtLeastOneTarget = false;
		string sTargets = string.Empty;
		for(int i = 0; i < bSpecialTarget.Length; i++)
		{
			bUniversal &= bSpecialTarget[i];
			bAtLeastOneTarget |= bSpecialTarget[i];
			if(bSpecialTarget[i])
				sTargets += sTarget[i] + "/";
		}
		
		
		if(string.IsNullOrEmpty(nameNewAsset))
		{
			bAdd = false;
			Debug.LogWarning("Can't add an empty name.");
		}
		else if(indexAssets.Contains(nameNewAsset))
		{
			bAdd = false;
			Debug.LogWarning(nameNewAsset + " already exists");
		}
		
		if(string.IsNullOrEmpty(typeNewAsset))
		{
			bAdd = false;
			Debug.LogWarning("Can't add an empty type.");
		}
		else if(GetType(typeNewAsset) == null)
		{
			if(GetType("UnityEngine." + typeNewAsset) !=  null)
				typeNewAsset = "UnityEngine." + typeNewAsset;
			else
			{
				bAdd = false;
				Debug.LogWarning(typeNewAsset + " is not a recognized type.");
			}
		}
		
		if(!bAtLeastOneTarget)
		{
			bAdd = false;
			Debug.LogWarning("You need to toggle at least one target");
		}
		
		if(bAdd)
		{
			XmlDocument xmlDoc = new XmlDocument();

		    xmlDoc.Load(sXmlConfiguration);
		
		    XmlNode nodeToAdd = xmlDoc.CreateElement("ASSETARRAY");
			
			XmlAttribute name = xmlDoc.CreateAttribute("name");
			name.Value = nameNewAsset;
			
			XmlAttribute type = xmlDoc.CreateAttribute("type");
			type.Value = typeNewAsset;
			
			XmlAttribute count = xmlDoc.CreateAttribute("count");
			count.Value = newSize.ToString();
			
			nodeToAdd.Attributes.Append(name);
			nodeToAdd.Attributes.Append(type);
			nodeToAdd.Attributes.Append(count);
			
			if(!bUniversal)
			{
				XmlAttribute targets = xmlDoc.CreateAttribute("target");
				targets.Value = sTargets;
				nodeToAdd.Attributes.Append(targets);
			}
			
			for(int i = 0; i < newSize; i++)
			{
				XmlNode asset = xmlDoc.CreateElement("ASSET");
				
				XmlAttribute path = xmlDoc.CreateAttribute("path");
				path.Value = string.Empty;
				
				asset.Attributes.Append(path);
				
				nodeToAdd.AppendChild(asset);
			}
			
			XmlNodeList nodeHolder = xmlDoc.GetElementsByTagName("HOLDER");
			
			nodeHolder[0].AppendChild(nodeToAdd);
			
			WriteXml( xmlDoc, sXmlConfiguration );
			
			Initialize();
		}
	}
	
	void DisplayModifyAsset()
	{
		int countTargetMod = 0;
		
		GUI.enabled = (Selected != -1);
		EditorGUILayout.Space();
		EditorGUILayout.LabelField("Modify Asset", titleStyle);
		GUILayout.BeginHorizontal();
		GUI.enabled = (Selected != 0) && (Selected != -1);
		if(GUILayout.Button("^"))
			Switch(Selected, Selected-1);
		GUI.enabled = (Selected != indexAssets.Count - 1) && (Selected != -1);
		if(GUILayout.Button("v"))
			Switch(Selected, Selected+1);
		GUILayout.EndHorizontal();
		
		GUI.enabled = (Selected != -1);
		
		nameModifiedAsset = EditorGUILayout.TextField("Asset Name", nameModifiedAsset, GUI.skin.textField);
		typeModifiedAsset = EditorGUILayout.TextField("Asset Type", typeModifiedAsset, GUI.skin.textField);
		modifiedCount = EditorGUILayout.IntField("Count ", modifiedCount, GUI.skin.textField);
		modifiedCount = Mathf.Clamp(modifiedCount, 1, 50);
		
		bool allTarget = EditorGUILayout.Toggle("All Targets", bModifiedAllTarget);
		
		if(bModifiedAllTarget != allTarget)
		{
			bModifiedAllTarget = allTarget;
			for(int i = 0; i < bModifiedSpecialTarget.Length; i++)
				bModifiedSpecialTarget[i] = bModifiedAllTarget;
		}
		
		for(int i = 0; i < bModifiedSpecialTarget.Length; i++)
		{
        	bModifiedSpecialTarget[i] = EditorGUILayout.Toggle("\t" + sTarget[i], bModifiedSpecialTarget[i]);
			if( allTarget && allTarget != bModifiedSpecialTarget[i] )
			{
				bModifiedAllTarget = bModifiedSpecialTarget[i];
			}
			else if( !bModifiedAllTarget && bModifiedAllTarget != bModifiedSpecialTarget[i] )
			{
				countTargetMod++;
			}
		}
		
		//All 
		if( countTargetMod == sTarget.Length )
		{
			bModifiedAllTarget = true;
		}
		countTargetMod = 0;
		
		if(GUILayout.Button("Modify"))
			ModifyAsset();
		EditorGUILayout.Space();
		GUI.enabled = true;
	}
	
	void ModifyAsset()
	{
		
		if(string.IsNullOrEmpty(nameModifiedAsset))
		{
			Debug.LogWarning("The name field is empty.");
			return;
		}
		else if(indexAssets.IndexOf(nameModifiedAsset) != Selected && indexAssets.IndexOf( nameModifiedAsset ) != -1 )
		{
			Debug.LogWarning( nameModifiedAsset + " already exists." );
			return;
		}
		
		indexAssets[Selected] = nameModifiedAsset;
		
		if(string.IsNullOrEmpty(typeModifiedAsset))
		{
			Debug.LogWarning("The type field is empty.");
			return;
		}
		else
		{
			System.Type newType = GetType(typeModifiedAsset);
			if(newType == null)
			{
				newType = GetType("UnityEngine." + typeModifiedAsset);
				if(newType == null)
				{
					Debug.LogWarning(typeModifiedAsset + " is not a type.");
					return;
				}
				else
					typeModifiedAsset = "UnityEngine." + typeModifiedAsset;
			}
			
			if(newType != typeAssets[Selected])
			{
				for(int i = 0; i < listObjects[Selected].Length; i++)
				{
					listObjects[Selected][i] = null;
					listAssets[Selected][i] = string.Empty;
				}
				typeAssets[Selected] = newType;
			}
			
		}
		
		bool bUniversal = true;
		bool bAtLeastOneTarget = false;
		string sTargets = string.Empty;
		for(int i = 0; i < bModifiedSpecialTarget.Length; i++)
		{
			bUniversal &= bModifiedSpecialTarget[i];
			bAtLeastOneTarget |= bModifiedSpecialTarget[i];
			if(bModifiedSpecialTarget[i])
				sTargets += sTarget[i] + "/";
		}
		
		if(!bAtLeastOneTarget)
		{
			Debug.LogWarning("You need to toggle at least one target");
			return;
		}
		
		XmlDocument xmlDoc = new XmlDocument();

	    xmlDoc.Load(sXmlConfiguration);
	
	    XmlNodeList node = xmlDoc.GetElementsByTagName("ASSETARRAY");
		
		string previousCount = node[Selected].Attributes["count"].Value;
		
		if(string.IsNullOrEmpty(previousCount) || previousCount == "1" && modifiedCount > 1)
		{
			System.Array.Resize<bool>(ref folderArrays, folderArrays.Length + 1);
			folderArrays[folderArrays.Length - 1] = false;
		}
		
		node[Selected].Attributes["name"].Value = nameModifiedAsset;
		node[Selected].Attributes["type"].Value = typeModifiedAsset;
		node[Selected].Attributes["count"].Value = modifiedCount.ToString();
		
		
		if(!bUniversal)
		{
			if(node[Selected].Attributes["target"] != null)
			{
				node[Selected].Attributes["target"].Value = sTargets;
			}
			else
			{
				XmlAttribute targets = xmlDoc.CreateAttribute("target");
				targets.Value = sTargets;
				node[Selected].Attributes.Append(targets);
			}
			targetAssets[Selected].Clear();
			for(int i = 0; i < bModifiedSpecialTarget.Length; i++)
			{
				if(bModifiedSpecialTarget[i])
					targetAssets[Selected].Add(pBuildTarget[i]);
			}
		}
		else
		{
			targetAssets[Selected].Clear();
		}
			
		
		int prevLength = listAssets[Selected].Length;
		System.Array.Resize<string>(ref listAssets[Selected].array, modifiedCount);
		System.Array.Resize<Object>(ref listObjects[Selected], modifiedCount);
		if(modifiedCount > prevLength)
		{
			for(int i = prevLength; i < modifiedCount; i++)
			{
				XmlNode asset = xmlDoc.CreateElement("ASSET");
				XmlAttribute path =  xmlDoc.CreateAttribute("path");
				asset.Attributes.Append(path);
				node[Selected].AppendChild(asset);
			}
		}
		else
		{
			XmlNodeList assetNodes = node[Selected].ChildNodes;
			for(int i = prevLength - 1; i >= modifiedCount; i--)
			{
				node[Selected].RemoveChild(assetNodes[i]);
			}
		}

		WriteXml( xmlDoc, sXmlConfiguration );
		
		Debug.Log(Path.GetFileName(sXmlConfiguration) + " saved.");
	}
	
	/// <summary>
	/// Switch the specified idx and idx2 (always change idx2 with idx).
	/// </summary>
	/// <param name='idx'>
	/// First index node
	/// </param>
	/// <param name='idx2'>
	/// Second index node
	/// </param>
	void Switch(int idx, int idx2)
	{
		Debug.Log("Index value : " + idx );
		Debug.Log("Index value 2 : " + idx2 );
		
		AssetArray arrayAssetTmp = listAssets[idx];
		listAssets[idx] = listAssets[idx2];
		listAssets[idx2] = arrayAssetTmp;
		
		Object[] arrayObjectTmp = listObjects[idx];
		listObjects[idx] = listObjects[idx2];
		listObjects[idx2] = arrayObjectTmp;
		
		string stringArrayTmp = indexAssets[idx];
		indexAssets[idx] = indexAssets[idx2];
		indexAssets[idx2] = stringArrayTmp;
		
		System.Type typeArrayTmp = typeAssets[idx];
		typeAssets[idx] = typeAssets[idx2];
		typeAssets[idx2] = typeArrayTmp;
		
		List<BuildTarget> pTargetTmp = targetAssets[idx];
		targetAssets[idx] = targetAssets[idx2];
		targetAssets[idx2] = pTargetTmp;
		
		XmlDocument xmlDoc = new XmlDocument();

	    xmlDoc.Load(sXmlConfiguration);
		
	    XmlNodeList node = xmlDoc.GetElementsByTagName("ASSETARRAY");
		
		XmlNodeList nodeHolder = xmlDoc.GetElementsByTagName("HOLDER");
		
		xmlDoc.RemoveAll();
		
		XmlNode nodeToSwitch = node[idx2].Clone();
		
		//If current index (idx2) is the highest must insert it before otherwise after (!!)
		if( idx < idx2 )
			nodeHolder[0].InsertBefore(nodeToSwitch, node[idx]);
		else
			nodeHolder[0].InsertAfter(nodeToSwitch, node[idx]);
		//Remove the elder node
		nodeHolder[0].RemoveChild(node[idx2]);
		
		xmlDoc.AppendChild( nodeHolder.Item(0) );
		WriteXml( xmlDoc, sXmlConfiguration );
		Selected = idx2;
		
		Repaint();
	}
	
	void GenerateEnum()
	{
		StreamWriter sw = new StreamWriter(Application.dataPath + "/Scripts/lwAssetHolderEnum.cs");
		sw.WriteLine("public enum lwAssetHolderEnum");
		sw.WriteLine("{");
		for(int i = 0; i < indexAssets.Count; i++)
		{
			string lineToWrite = "\t" + indexAssets[i].Replace(" ","_");
			if(i != indexAssets.Count - 1)
				lineToWrite += ",";
			sw.WriteLine(lineToWrite);
		}
		sw.WriteLine("};");
		sw.Close();
		Debug.Log("Enum Generated.");
	}
	
	void Reset<T>(ref System.Collections.Generic.List<T> list)
	{
		if(list == null)
			list =  new System.Collections.Generic.List<T>();
		else
			list.Clear();
	}
	
	void Initialize()
	{
		// On réinitialise en premier les listes
		Reset<string>(ref indexAssets);
		Reset<System.Type>(ref typeAssets);
		Reset<List<BuildTarget>>(ref targetAssets);
		
		if(!File.Exists(sXmlConfiguration))
		{
			//bXmlNotFound = true;
			return;
		}
		
		//bXmlNotFound = false;
		
		
		XmlDocument xmlDoc = new XmlDocument();

	    xmlDoc.Load(sXmlConfiguration);
	
	    XmlNodeList nodeList = xmlDoc.GetElementsByTagName("ASSETARRAY");
	
		listAssets = new AssetArray[nodeList.Count];
		
		string sAssetName = string.Empty;
		string sTargetValue = string.Empty;
		System.Type sAssetType = null;
		int count = -1;
		int nbArrays = 0;
		
		for(int i = 0; i < nodeList.Count; i++)
		{
			sAssetName = nodeList[i].Attributes["name"].Value;
			sAssetType = GetType(nodeList[i].Attributes["type"].Value);
			string sCount = nodeList[i].Attributes["count"].Value;
			//Si la target n'est pas à null on donne la valeur à notre TargetValue sinon on met empty
			if(nodeList[i].Attributes["target"] != null)
				sTargetValue = nodeList[i].Attributes["target"].Value;
			else
				sTargetValue = string.Empty;
			
			// Si l'attribut count n'est pas défini c'est que l'on se trouve face à un asset simple (-> count = 1)
			if(string.IsNullOrEmpty(sCount))
				count = 1;
			else
				System.Int32.TryParse(sCount, out count);
			
			if(!string.IsNullOrEmpty(sAssetName) && sAssetType != null && count > 0)
			{
				// Si la liste contient déjà la clé on le signale
				if(!indexAssets.Contains(sAssetName))
				{
					// Si le type définit dans le XML est un array on le signale
					if(!sAssetType.IsArray)
					{
						// Sinon on remplit les listes avec la clé
						indexAssets.Add(sAssetName);
						typeAssets.Add(sAssetType);
						
						targetAssets.Add(new List<BuildTarget>());
						
						if(!string.IsNullOrEmpty(sTargetValue))
						{
							for(int j = 0; j < sTarget.Length; j++)
							{
								if(sTargetValue.Contains(sTarget[j]) )
								{
									targetAssets[targetAssets.Count-1].Add(pBuildTarget[j]);
								}
							}
						}
						
						listAssets[i] = new AssetArray(count);
						XmlNodeList pathList = nodeList[i].ChildNodes;
						
						
						for(int j = 0; j < pathList.Count; j++)
						{
							listAssets[i][j] = 	pathList[j].Attributes["path"].Value;
						}
						// Si c'était un tableau on incrémente nbArrays
						if(count > 1)
							nbArrays++;
					}
					else
						Debug.LogWarning(sAssetName + " is an Array Type. Please use the argument count");
				}
				else
					Debug.LogWarning("The key " + sAssetName + " already exists !");
			}
			else
				Debug.LogWarning(sAssetName + " has an invalid parameter.");
		}
		
		
		if(indexAssets.Count == 0)
			return;
		
		
		// En premier on vérifie que notre liste a le bon nombre de rangées pour afficher les assets
		int size = listAssets.Length;
		
		if(listObjects == null)
			listObjects = new Object[size][];
		else if(listObjects.Length < size)
			listObjects = Resize<Object>(listObjects, size);
		
		
		for(int j = 0; j < listObjects.Length; j++)
		{
			// Ensuite on vérifie pour chaque tableau d'assets si il y a le bon nombre (un asset simple est inclu dans un tableau de longueur 1)
			int begin = 0;
			if(listObjects[j] == null)
				listObjects[j] = new Object[listAssets[j].Length];
			else if (listObjects[j].Length < listAssets[j].Length)
			{
				begin = listObjects[j].Length;
				System.Array.Resize<Object>(ref listObjects[j], listAssets[j].Length);
			}
			
			// Enfin on charge les objets à afficher dans l'inspector
			for(int k = begin; k < listObjects[j].Length; k++)
			{
				string pathToLoad = listAssets[j][k];
				if(!string.IsNullOrEmpty(pathToLoad))
				{
					int lastIdx = pathToLoad.LastIndexOf(".");
					if(lastIdx > 1)
						pathToLoad = pathToLoad.Substring(1, lastIdx - 1);
					else
						pathToLoad = pathToLoad.Substring(1);
					
					listObjects[j][k] = Resources.Load(pathToLoad);
					// Si l'objet n'est plus trouvé on remet le chemin de l'objet à null
					if(listObjects[j][k] == null)
						listAssets[j][k] = string.Empty;
				}
				else
					listObjects[j][k] = null;
			}
				
		}
		
		// On définit les booléens pour les folders correspondant au nombre de tableaux dans le xml
		folderArrays = new bool[nbArrays];
		for(int j = 0; j < folderArrays.Length; j++)
			folderArrays[j] = false;
			
	}
	
	// Récupère un type à partir d'une chaîne de caractère
	System.Type GetType( string TypeName )
	{
		// On vérifie en premier si c'est un type C# (peu probable)
    	/*System.Type type = System.Type.GetType( TypeName );
		
    	if( type != null )
        	return type;*/
		
		// Sinon on cherche parmi toutes les références d'Unity et de notre projet
		foreach(System.Reflection.AssemblyName nameAss in System.Reflection.Assembly.GetExecutingAssembly().GetReferencedAssemblies())
		{
			System.Type type = System.Reflection.Assembly.Load(nameAss).GetType( TypeName );
			if( type != null )
        		return type;
		}
		
		return null;
		
	}
 
	// Permet de rajouter des colonnes 
	T[][] Resize<T>(T[][] array, int newSize)
	{
		T[][] tmp = new T[newSize][];
		
		int minLength = Mathf.Min(newSize, array.Length);
		
		for(int i = 0; i < minLength; i++)
		{
			if(tmp[i] == null)
				tmp[i] = new T[array[i].Length];
			System.Array.Copy(array[i], tmp[i], array[i].Length);
		}	
		return tmp;
	}
	
	string GetResourcePath( string assetPath )
	{
		string pattern = @"^Assets\/AssetHolders\/Resources(.+)";
		Match match = Regex.Match( assetPath, pattern );
		if( match.Success )
		{
			return match.Groups[1].Value;
		}

		return string.Empty;
	}
	
	int Selected
	{
		get{return nCurrentSelected;}
		set
		{
			nCurrentSelected = value;
			if(nCurrentSelected != -1)
			{
				modifiedCount = listAssets[nCurrentSelected].Length;
				nameModifiedAsset = indexAssets[nCurrentSelected];
				typeModifiedAsset = typeAssets[nCurrentSelected].ToString();
				targetModifiedAsset = targetAssets[nCurrentSelected];
				
				bModifiedAllTarget = targetModifiedAsset.Count == sTarget.Length || targetModifiedAsset.Count == 0;
				for(int i = 0; i < bModifiedSpecialTarget.Length; i++)
					bModifiedSpecialTarget[i] = targetModifiedAsset.Contains(pBuildTarget[i]) || bModifiedAllTarget;
				
			}
		}
	}
}